home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / 7Edit 3.1 / Sources / SVEditGXPrinting.c < prev    next >
Encoding:
Text File  |  1995-11-20  |  14.8 KB  |  536 lines  |  [TEXT/MPCC]

  1. // SVEditGXPrinting.c
  2. //
  3. // 7Edit 3.1d1. Original version by Jon Lansdell and Nigel Humphreys.
  4. // 3.1 updates by Greg Sutton.
  5. // GX printing by Don Swatman
  6. // ©Apple Computer Inc 1995, all rights reserved.
  7.  
  8. // Adds GX printing functionality to 7Edit
  9.  
  10. #include <Gestalt.h>
  11. #include <Graphics routines.h>
  12. #include <GXPrinting.h>
  13. #include <graphics toolbox.h>
  14. #include "QDLibrary.h"
  15.  
  16.  
  17. #include "SVEditGXPrinting.h"
  18. #include "SVEditWindow.h"
  19. #include "SVEditGlobals.h"
  20. #include "SVEditMain.h"
  21.  
  22. // Constants
  23.  
  24. #define        kGraphicsHeapSize    ((long) 300 * 1024)
  25.  
  26. // Globals
  27. gxGraphicsClient gClient;
  28.  
  29.  
  30. //-------------------------------------------------------
  31. //       InitGXIfPresent
  32. //
  33. // This uses Gestalt() to see if QuickDraw GX is present.
  34. // If it is, it then initialises the GX managers.
  35. // If it isn't, then it removes the GX file menu item(s).
  36. //-------------------------------------------------------
  37.  
  38. #pragma segment Main
  39.  
  40. void InitGXIfPresent(void)
  41. {
  42.     long gxVersion;
  43.     long gxPrintVersion;
  44.  
  45.     gGXIsPresent = false;
  46.  
  47. // Check to see whether QuickDraw GX is available.
  48.     if (Gestalt(gestaltGXVersion, &gxVersion) == noErr)
  49.         if (Gestalt(gestaltGXPrintingMgrVersion, &gxPrintVersion) == noErr)
  50.             gGXIsPresent = true;
  51.  
  52.     if (gGXIsPresent)
  53.     {
  54. // Initialize QuickDraw GX.
  55.         gClient = GXNewGraphicsClient(nil, kGraphicsHeapSize, (gxClientAttribute) 0);
  56.         GXEnterGraphics();
  57.         GXInitPrinting();
  58.     }
  59.     else
  60.     {
  61. // No QuickDraw GX, so remove extra file menu item(s)
  62.         DelMenuItem ( myMenus[fileM], fmPrintOne);
  63.     }
  64. }
  65.  
  66. //-------------------------------------------------------
  67. //       CleanUpGXIfPresent
  68. //
  69. // If GX was installed (i.e. gGXIsPresent) then remove
  70. // the GX managers.
  71. //-------------------------------------------------------
  72.  
  73. #pragma segment Main
  74.  
  75. void CleanUpGXIfPresent(void)
  76. {
  77.     if (gGXIsPresent)
  78.     {
  79.         GXExitPrinting();
  80.         GXDisposeGraphicsClient(gClient);
  81.         GXExitGraphics();
  82.     }
  83. }
  84.  
  85. //-------------------------------------------------------
  86. //       ConvertMenuActualToGXMenu
  87. //
  88. // This converts an item number as returned by MenuKey()
  89. // or MenuSelect() to the value used internally. The reason
  90. // you have to this is because a non gx application has
  91. // less items in the file menu.
  92. //-------------------------------------------------------
  93.  
  94. #pragma segment Main
  95.  
  96. short ConvertMenuActualToGXMenu ( short theItem )
  97. {
  98.     short menuItem;
  99.     
  100.     menuItem = theItem;    
  101.     if (!gGXIsPresent)
  102.     {
  103.         if (theItem == fmNoGXPrint)
  104.             menuItem = fmPrint;
  105.         else
  106.             if (theItem == fmNoGXQuit)
  107.                 menuItem = fmQuit;
  108.     }
  109.     return menuItem;
  110. }
  111.  
  112. //-------------------------------------------------------
  113. //       GetRectOfPage
  114. //
  115. // This returns a QuickDraw rect for the current printer page.
  116. // If gx is not present if uses rPage from the document's THPrint.
  117. // If gx is present then we get a GXRectangle from the requested
  118. // page's format. It then converts this to a Rect. This could be
  119. // extended to handle custom formated pages.
  120. //-------------------------------------------------------
  121.  
  122. #pragma segment Main
  123.  
  124. void GetRectOfPage( DPtr  theDoc,
  125.                                         Rect  *pageRect )
  126. {
  127.     gxFormat        pageFormat;
  128.     gxRectangle pageSize;
  129.     gxRectangle paperSize;
  130.  
  131.     if (gGXIsPresent)
  132.     {
  133.             pageFormat = GXGetJobFormat(theDoc->documentJob, 1);
  134.             GXGetFormatDimensions(pageFormat, &pageSize, &paperSize);
  135.     // Convert to a QD Rect
  136.             FixedRectToShort( &pageSize, pageRect );
  137.     }
  138.     else
  139.         *pageRect = (*(theDoc->thePrintSetup))->prInfo.rPage;
  140.     OffsetRect( pageRect, -pageRect->left, -pageRect->top);
  141. }
  142.  
  143. //-------------------------------------------------------
  144. //       AdjustMenusForGXPrintDialogs
  145. //
  146. // This enables or disables menu's when the GX print dialog
  147. // is being displayed.
  148. //-------------------------------------------------------
  149.  
  150. #pragma segment GXPrintSeg
  151.  
  152. void AdjustMenusForGXPrintDialogs( Boolean dialogGoingUp )
  153. {
  154.     if (dialogGoingUp)
  155.     {
  156.         DisableItem(myMenus[appleM], aboutItem);
  157.         DisableItem(myMenus[fileM], 0);
  158.         if (gWCount)
  159.         {
  160.             DisableItem(myMenus[fontM], 0);
  161.             DisableItem(myMenus[sizeM], 0);
  162.             DisableItem(myMenus[styleM], 0);
  163.  
  164.             DisableItem(myMenus[editM], selectAllCommand);
  165.         }
  166.         HiliteMenu(0);
  167.     }
  168.     else
  169.     {
  170.                 EnableItem(myMenus[appleM], aboutItem);
  171.                 EnableItem(myMenus[fileM], 0);
  172.                 EnableItem(myMenus[editM], 0);
  173.                 if (gWCount)
  174.                 {
  175.                   EnableItem(myMenus[fontM], 0);
  176.                   EnableItem(myMenus[sizeM], 0);
  177.                   EnableItem(myMenus[styleM], 0);
  178.             
  179.                   EnableItem(myMenus[editM], selectAllCommand);
  180.                 }
  181.                 MaintainMenus();
  182.     }
  183.     
  184.     DrawMenuBar();
  185. }
  186.  
  187. //-------------------------------------------------------
  188. //       SetupGXEditMenuRec
  189. //
  190. // Sets up the gxEditMenuRecord. This is used by the
  191. // GX dialogs so that they know where the items in the
  192. // Edit Menu are
  193. //-------------------------------------------------------
  194.  
  195. #pragma segment GXPrintSeg
  196.  
  197. void SetupGXEditMenuRec(gxEditMenuRecord *editMenuRec)
  198.     {
  199.         editMenuRec->editMenuID = editID;
  200.         editMenuRec->cutItem    =   cutCommand;
  201.         editMenuRec->copyItem   =   copyCommand;
  202.         editMenuRec->pasteItem  =   pasteCommand;
  203.         editMenuRec->clearItem  =   clearCommand;
  204.         editMenuRec->undoItem   =   undoCommand;
  205.     }
  206.  
  207. //-------------------------------------------------------
  208. //       DoGXPageSetup
  209. //
  210. //  Puts up a GX Page Setup dialog
  211. //-------------------------------------------------------
  212.  
  213. #pragma segment GXPrintSeg
  214.  
  215. Boolean DoGXPageSetup ( DPtr theDoc )
  216.     {
  217.         Boolean          result = false;
  218.             OSErr            theErr;
  219.             gxDialogResult   dialogResult;
  220.             gxEditMenuRecord editMenuRec;
  221.             
  222.             if (gGXIsPresent)
  223.                 if (theDoc)
  224.                 {
  225.                     AdjustMenusForGXPrintDialogs(true);
  226.                     SetupGXEditMenuRec( &editMenuRec );
  227.  
  228. // Display the Page Setup dialog box.
  229.                     dialogResult = GXJobDefaultFormatDialog ( theDoc->documentJob, &editMenuRec);
  230.                     theErr = GXGetJobError(theDoc->documentJob);
  231.  
  232.                     AdjustMenusForGXPrintDialogs(false);
  233.  
  234. // Return True, if there are no Errors and the OK button was clicked
  235.                     result = ((theErr == noErr) && (dialogResult == gxOKSelected));
  236.                 }
  237.         return(result);
  238.     }
  239.  
  240.  
  241. //-------------------------------------------------------
  242. //       struct GXPrintSpoolDataRec
  243. //
  244. //  Used to pass information during printing
  245. //-------------------------------------------------------
  246.  
  247. typedef struct GXPrintSpoolDataRec
  248. {
  249.     gxRectangle   pageArea;                /* Page rectangle. */
  250.     gxViewPort    printViewPort;  /* View port we're printing in. */
  251. } GXPrintSpoolDataRec, *GXPrintSpoolDataPtr;
  252.  
  253. //-------------------------------------------------------
  254. //       PrintAShape
  255. //
  256. //  Called after shape translation. It checks to see if any shape
  257. // it recieves are drawable, the draws it in the GX view port.
  258. // Information in the form of a pointer to a GXPrintSpoolDataRec
  259. // is passed in the refCon.
  260. //-------------------------------------------------------
  261.  
  262. #pragma segment GXPrintSeg
  263.  
  264. OSErr PrintAShape(gxShape currentShape, long refCon)
  265. {
  266.     GXPrintSpoolDataPtr spoolData;
  267.     gxShapeType         theShapeType;
  268.  
  269. // Get the spool data from the refCon
  270.     spoolData = (GXPrintSpoolDataPtr) refCon;
  271.  
  272. // Don't waste time spooling the shape if it's being drawn off the page.
  273.  
  274.     theShapeType = GXGetShapeType(currentShape);
  275.     if (   (theShapeType == gxEmptyType)
  276.             || (theShapeType == gxFullType)
  277.             || (theShapeType == gxPictureType)
  278.             || GXTouchesBoundsShape(&spoolData->pageArea, currentShape) )
  279.     {
  280.  
  281. // Set the ports and draw it
  282.         GXSetShapeViewPorts(currentShape, 1, &spoolData->printViewPort);
  283.         GXDrawShape(currentShape);
  284.     }
  285.     return (OSErr) GXGetGraphicsError(nil);
  286. }
  287.  
  288. //-------------------------------------------------------
  289. //       DuplicateStyleTERec
  290. //
  291. // This copies the styled TERec in theDoc. It puts it into
  292. // the destPort
  293. //-------------------------------------------------------
  294.  
  295. #pragma segment Main
  296.  
  297. void DuplicateStyleTERec( TEHandle  hSourceTE,
  298.                                                     TEHandle *hDestTE,
  299.                                                     Rect     *destRect,
  300.                                                     GrafPtr   destPort )
  301. {
  302.     GrafPtr oldPort;
  303.     short   oldSelStart;
  304.     short   oldSelEnd;
  305.     StScrpHandle printerTextStyles;
  306.     
  307. // Set up the ports
  308.     GetPort(&oldPort);
  309.     SetPort(destPort);
  310.     
  311. // Create a temporary Text Edit and copy the windows text edit into it
  312.     *hDestTE = TEStyleNew(destRect, destRect);
  313.  
  314. // Select all the text (preserving the previous settings) so that we can use 
  315. // GetTylScrap (or TEGetStyleScrapHandle ) to get the style of the whole TERec
  316.     oldSelStart = (*hSourceTE)->selStart;
  317.     oldSelEnd   = (*hSourceTE)->selEnd;
  318.     TESetSelect(0,(*hSourceTE)->teLength, hSourceTE);
  319.  
  320. // Get the style
  321.     printerTextStyles = GetStylScrap(hSourceTE);
  322.  
  323. // Revert the selection range
  324.     TESetSelect(oldSelStart, oldSelEnd, hSourceTE);
  325.  
  326. // Move the text from the documents TERec and add the style (got above) to it
  327.     HLock((Handle)((*hSourceTE)->hText));
  328.     TEStyleInsert ( (Ptr)*((*hSourceTE)->hText),
  329.                                     (*hSourceTE)->teLength,
  330.                                     printerTextStyles,
  331.                                     *hDestTE);        
  332.     HUnlock((Handle)((*hSourceTE)->hText));
  333.  
  334. // Deactivat the temporary TERec
  335.     TEDeactivate(*hDestTE);
  336.     
  337. // Reset the port
  338.     SetPort(oldPort);
  339. }
  340.  
  341. //-------------------------------------------------------
  342. //       GXPrintLoop
  343. //
  344. // This does the actual printing. It creates a invisible window
  345. // to draw into. It duplicates the Text Edit record in the 
  346. // document to a temporary record. It puts up the progress
  347. // dialog then it steps through the pages. At each page, it
  348. // clips the text edit rec so it doesn't draw lines of text
  349. // over two pages. It then uses TEUpdate to draw each page and
  350. // finally scroll's the text edit rec ready for the next page.
  351. //-------------------------------------------------------
  352.  
  353.  
  354. #pragma segment GXPrintSeg
  355.  
  356. OSErr GXPrintLoop ( DPtr theDoc)
  357. {
  358.     OSErr      theErr = noErr;
  359.      WindowPtr  imagingWind;              // Temp window we're going to draw into
  360.     gxViewPort printViewPort;            // Printer view port
  361.     Rect       tempWindRect = {0,0,0,0}; // Bounds for temp window
  362.   TEHandle   tempTE;                   // Copy of the documents text edit record
  363.      PageEndsArray pageEnds;           
  364.     short      numDocPages;
  365.     long       firstPage;
  366.     long       lastPage;
  367.     long       numPagesToPrint;
  368.     long       pageCounter;
  369.     Point      patStretch = {1,1};
  370.     gxFormat   pageFormat;
  371.     Rect       everywhereRect;
  372.     Str255     windTitle;
  373.     GXPrintSpoolDataRec spoolData;
  374.     Rect       printerPage;
  375.     Rect       rectToClip;
  376.  
  377. // Create a window to draw into. It's bounds are small(0,0,0,0)
  378. // and it's not shown so it doesn't appear to the user 
  379.     imagingWind = NewWindow ( nil, &tempWindRect, "\p",
  380.                                                         false, documentProc, (WindowPtr)-1,
  381.                                                         false, 0);
  382.  
  383. // Set the port to the imaging port
  384.     SetPort((GrafPtr)imagingWind);
  385.     
  386. // Get the size of the printers page 
  387.     GetRectOfPage ( theDoc, &printerPage );
  388.  
  389. // Duplicate the text edit record from the document
  390.     DuplicateStyleTERec( theDoc->theText, &tempTE, &printerPage, (GrafPtr)imagingWind );
  391.  
  392.  
  393. // Work out the size of each page using GetPageEnds. This stops text
  394. //  drawing over two pages
  395.  
  396.     (*tempTE)->destRect = printerPage;
  397.     GetPageEnds(printerPage.bottom-printerPage.top,
  398.                             tempTE,
  399.                             pageEnds,
  400.                             &numDocPages);
  401.     
  402.  
  403. // Determine which pages the user selected to print, and print
  404. // only those pages that are actually in the document. 
  405.     GXGetJobPageRange(theDoc->documentJob, &firstPage, &lastPage);
  406.     if (lastPage > numDocPages)
  407.         lastPage = numDocPages;
  408.  
  409. // Calculate the number of pages to print and begin printing. 
  410.     numPagesToPrint = lastPage - firstPage + 1;
  411.     theErr = GXGetJobError(theDoc->documentJob);
  412.     if (!theErr)
  413.     {
  414. // Get the title of the window as we'll use this for the name we call the print job
  415.         GetWTitle ( theDoc->theWindow, windTitle);
  416.  
  417. // Put up the print progress dialog
  418.         GXStartJob( theDoc->documentJob,
  419.                                 windTitle, 
  420.                                 numPagesToPrint);
  421.         theErr = GXGetJobError(theDoc->documentJob);
  422.         if (!theErr)
  423.         {
  424. // Create a new view port for printing and set our translator
  425. //    rects to "wide open" so that they include all data we're
  426. //    drawing. For each page we print, call GXStartPage, draw,
  427. //    and call GXFinishPage. 
  428.             SetRect(&everywhereRect, 0, 0, 32767, 32767);
  429.             printViewPort = GXNewViewPort(gxScreenViewDevices);
  430.         
  431.             for (pageCounter = firstPage; (theErr == noErr) && (pageCounter <= lastPage); pageCounter++)
  432.             {
  433. // Get the page's format and start printing the page.
  434.                 pageFormat = GXGetJobFormat(theDoc->documentJob, 1);
  435.         
  436.                 GXStartPage(theDoc->documentJob, pageCounter, pageFormat, 1, &printViewPort);                                
  437.                 theErr = GXGetJobError(theDoc->documentJob);
  438.         
  439. // If there were no errors, set up the translator, draw
  440. // the QuickDraw data for current page, and remove the
  441. // translator.
  442.                 if (!theErr)
  443.                 {
  444.     // Set up spool data
  445.                     spoolData.printViewPort = printViewPort;
  446.                     GXGetFormatDimensions( pageFormat, &spoolData.pageArea, nil);
  447.  
  448.   // Install the translator
  449.                     GXInstallQDTranslator((GrafPtr)imagingWind,
  450.                                                                 gxDefaultOptionsTranslation,
  451.                                                                 &everywhereRect,
  452.                                                                 &everywhereRect,
  453.                                                                 patStretch,
  454.                                                                 NewgxShapeSpoolProc ( PrintAShape ),
  455.                                                                 &spoolData);
  456.  
  457. // Make sure it draws into the correct QuickDraw window
  458.                     SetPort((GrafPtr)imagingWind);
  459.  
  460. // Clip the page to the size of the current page
  461.                     rectToClip = printerPage;
  462.                     if (pageCounter == 1)
  463.                         rectToClip.bottom = rectToClip.top + pageEnds[pageCounter-1];
  464.                     else
  465.                         rectToClip.bottom = rectToClip.top
  466.                                                                 + ( pageEnds[pageCounter-1] - pageEnds[pageCounter-2] );
  467.                     ClipRect(&rectToClip);
  468.  
  469. // Use TEUpdate to do the drawing
  470.                     TEUpdate(&printerPage, tempTE);
  471.  
  472. // Remove the Translator
  473.                     GXRemoveQDTranslator((GrafPtr)imagingWind, nil);
  474.  
  475. // Finish off this page
  476.                     GXFinishPage(theDoc->documentJob);
  477.  
  478. // Scroll the text edit down to the next page
  479.                     if (pageCounter < lastPage)
  480.                         TEScroll(0,rectToClip.top-rectToClip.bottom, tempTE);
  481.                 }
  482.             }
  483. // All done, so finish the printer job and dispose of the GXView port
  484.             GXFinishJob(theDoc->documentJob);
  485.             theErr = GXGetJobError(theDoc->documentJob);
  486.             GXDisposeViewPort(printViewPort);
  487.         }
  488.     }
  489.  
  490. // Dispose of temporary TERec and imaging window
  491.     TEDispose ( tempTE );
  492.     DisposeWindow ( imagingWind );
  493.  
  494.     return theErr;
  495. }
  496.     
  497. //-------------------------------------------------------
  498. //       GXPrintDocument
  499. //
  500. // This puts up the print dialog box, then calls GXPrintLoop()
  501. // to do the actual printing.
  502. //-------------------------------------------------------
  503.  
  504. #pragma segment GXPrintSeg
  505.  
  506. OSErr GXPrintDocument ( DPtr    theDoc,
  507.                                                 Boolean askUser )
  508. {
  509.     OSErr                        err = noErr;
  510.     gxEditMenuRecord    editMenuRec;
  511.     gxDialogResult        dialogResult;
  512.  
  513. // Put up the print dialog if askUser is set to true
  514.     if (!askUser)
  515.         dialogResult = gxOKSelected;
  516.     else
  517.     {
  518. // Set up the edit menu record so GX knows how to gray it
  519.         SetupGXEditMenuRec( &editMenuRec );
  520.     
  521.         AdjustMenusForGXPrintDialogs(true);
  522.         dialogResult = GXJobPrintDialog(theDoc->documentJob, 
  523.                                                             &editMenuRec);
  524.         AdjustMenusForGXPrintDialogs(false);
  525.     }
  526.  
  527. // if ok selected, then print the pages
  528.     if (dialogResult == gxOKSelected)
  529.         err = GXPrintLoop(theDoc);
  530.     else
  531.         err = userCanceledErr;
  532.  
  533.     return err;
  534. }
  535.  
  536.